package com.mmg.cosplay.service;

import com.alibaba.dashscope.aigc.multimodalconversation.AudioParameters;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
import com.alibaba.dashscope.common.MultiModalMessage;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.exception.UploadFileException;
import com.alibaba.dashscope.utils.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.Base64;
import java.util.HashMap;

@Service
public class VoiceService {

    private static final Logger logger = LoggerFactory.getLogger(VoiceService.class);

    @Value("${langchain4j.community.dashscope.chat-model.api-key}")
    private String apiKey;

    // 阿里云百炼平台模型名称
    private static final String TTS_MODEL = "qwen3-tts-flash";
    private static final String ASR_MODEL = "qwen3-asr-flash";

    /**
     * 语音转文字 (ASR - Automatic Speech Recognition)
     * 使用阿里云百炼平台的语音识别服务
     * 参考您的测试代码实现
     */
    public String speechToText(MultipartFile audioFile) throws Exception {
        try {
            // 设置API密钥
            Constants.apiKey = apiKey;

            // 验证音频文件
            if (audioFile == null || audioFile.isEmpty()) {
                throw new IllegalArgumentException("音频文件不能为空");
            }

            // 检查文件类型
            String contentType = audioFile.getContentType();
            if (contentType == null || !isAudioFile(contentType)) {
                throw new IllegalArgumentException("不支持的音频格式，请上传wav、mp3、m4a格式的音频文件");
            }

            // 检查文件大小 (限制为10MB)
            if (audioFile.getSize() > 10 * 1024 * 1024) {
                throw new IllegalArgumentException("音频文件大小不能超过10MB");
            }

            String fileName = audioFile.getOriginalFilename();
            long fileSize = audioFile.getSize();

            logger.info("开始语音识别，文件: {}, 大小: {} bytes", fileName, fileSize);

            // 将MultipartFile保存为临时文件
            File tempFile = saveMultipartFileToTemp(audioFile);
            String localFilePath = tempFile.getAbsolutePath();

            try {
                // 创建多模态对话实例
                MultiModalConversation conv = new MultiModalConversation();

                // 构建用户消息，包含音频文件
                MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
                        .content(Arrays.asList(new HashMap<String, Object>(){{put("audio", localFilePath);}}
                        ))
                        .build();

                // 构建请求参数
                MultiModalConversationParam param = MultiModalConversationParam.builder()
                        .model(ASR_MODEL)  // 使用语音识别模型
                        .apiKey(apiKey)
                        .message(userMessage)
                        .build();

                // 调用语音识别服务
                logger.info("调用阿里云语音识别服务...");
                MultiModalConversationResult result = conv.call(param);

                if (result != null && result.getOutput() != null && result.getOutput().getChoices() != null
                        && !result.getOutput().getChoices().isEmpty()) {

                    // 获取识别结果文本
                    String recognizedText = result.getOutput().getChoices().get(0).getMessage().getContent().get(0).get("text").toString();
                    logger.info("语音识别成功，结果: {}", recognizedText);
                    return recognizedText != null ? recognizedText.trim() : "识别结果为空";

                } else {
                    logger.warn("语音识别返回空结果");
                    return "语音识别失败，请重试";
                }

            } finally {
                // 清理临时文件
                if (tempFile.exists()) {
                    boolean deleted = tempFile.delete();
                    logger.debug("临时文件清理结果: {}", deleted);
                }
            }

        } catch (NoApiKeyException e) {
            logger.error("API密钥未配置", e);
            throw new Exception("API密钥未配置，请检查配置文件", e);
        } catch (UploadFileException e) {
            logger.error("文件上传失败", e);
            throw new Exception("文件上传失败: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("语音转文字失败", e);
            throw new Exception("语音转文字失败: " + e.getMessage(), e);
        }
    }

    /**
     * 文字转语音 (TTS - Text To Speech)
     * 使用阿里云百炼平台的语音合成服务
     * 参考您的测试代码实现
     */
    public byte[] textToSpeech(String text) throws Exception {
        try {
            // 设置API密钥
            Constants.apiKey = apiKey;

            if (text == null || text.trim().isEmpty()) {
                throw new IllegalArgumentException("文本内容不能为空");
            }

            // 对文本进行简单清理
            text = text.trim()
                    .replaceAll("\\s+", "")
                    .replaceAll("\\*\\*", "")
                    .replaceAll("\\n", "")
                    .replaceAll("\\r", "")
                    .replaceAll("#", "")
                    .replaceAll("##", "")
                    .replaceAll("###", "")
                    .replaceAll("-","")
                    .replaceAll("--", "")
                    .replaceAll("---", "")
                    .replaceAll("``", "")
                    .replaceAll("\\*", "");

            // 文本长度限制 (根据阿里云文档建议)
            if (text.length() > 300) {
                text = text.substring(0, 300);
                logger.warn("文本长度超过限制，已截取前300个字符");
            }

            logger.info("开始文字转语音，文本长度: {}", text.length());
            logger.info("待合成文本: {}", text.substring(0, Math.min(50, text.length())));

            // 创建多模态对话实例
            MultiModalConversation conv = new MultiModalConversation();

            // 构建语音合成请求参数
            MultiModalConversationParam param = MultiModalConversationParam.builder()
                    .model(TTS_MODEL)                           // 使用语音合成模型
                    .text(text)                                 // 待合成的文本
                    .apiKey(apiKey)
                    .voice(AudioParameters.Voice.CHERRY) // 默认音色Cherry
                    .build();

            // 调用语音合成服务
            logger.info("调用阿里云语音合成服务...");
            MultiModalConversationResult result = conv.call(param);

            if (result != null && result.getOutput() != null && result.getOutput().getAudio() != null) {
                String audioUrl = result.getOutput().getAudio().getUrl();
                logger.info("语音合成成功，音频URL: {}", audioUrl);

                // 下载音频文件并返回字节数组
                byte[] audioBytes = downloadAudioFromUrl(audioUrl);
                logger.info("音频下载完成，大小: {} bytes", audioBytes.length);

                return audioBytes;

            } else {
                logger.warn("语音合成返回空结果");
                throw new Exception("语音合成失败：服务返回空结果");
            }

        } catch (NoApiKeyException e) {
            logger.error("API密钥未配置", e);
            throw new Exception("API密钥未配置，请检查配置文件", e);
        } catch (UploadFileException e) {
            logger.error("语音合成上传失败", e);
            throw new Exception("语音合成上传失败: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("文字转语音失败", e);
            throw new Exception("文字转语音失败: " + e.getMessage(), e);
        }
    }

    /**
     * 将MultipartFile保存为临时文件
     */
    private File saveMultipartFileToTemp(MultipartFile multipartFile) throws IOException {
        String originalFilename = multipartFile.getOriginalFilename();
        String fileExtension = "";

        if (originalFilename != null && originalFilename.contains(".")) {
            fileExtension = originalFilename.substring(originalFilename.lastIndexOf('.'));
        } else {
            fileExtension = ".mp3"; // 默认扩展名
        }
        // 创建临时文件，使用系统临时目录
        File tempFile = Files.createTempFile("voice_upload_", fileExtension).toFile();

        // 复制MultipartFile内容到临时文件
        try (InputStream inputStream = multipartFile.getInputStream()) {
            Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
        }

        logger.debug("临时文件已创建: {}", tempFile.getAbsolutePath());
        logger.debug("文件URI: {}", tempFile.toURI().toString());
        return tempFile;
    }

    /**
     * 从URL下载音频文件
     */
    private byte[] downloadAudioFromUrl(String audioUrl) throws IOException {
        logger.info("开始下载音频文件: {}", audioUrl);

        try (InputStream inputStream = new URL(audioUrl).openStream();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            byte[] audioBytes = outputStream.toByteArray();
            logger.info("音频文件下载完成，大小: {} bytes", audioBytes.length);
            return audioBytes;

        } catch (Exception e) {
            logger.error("下载音频文件失败: {}", audioUrl, e);
            throw new IOException("下载音频文件失败: " + e.getMessage(), e);
        }
    }

    /**
     * 检查是否为音频文件
     */
    private boolean isAudioFile(String contentType) {
        return contentType.startsWith("audio/") ||
                contentType.equals("application/octet-stream"); // 某些音频文件可能被识别为这种类型
    }

    /**
     * 将字节数组转换为Base64编码
     */
    public String encodeToBase64(byte[] audioBytes) {
        return Base64.getEncoder().encodeToString(audioBytes);
    }

    /**
     * 从Base64解码为字节数组
     */
    public byte[] decodeFromBase64(String base64Audio) {
        return Base64.getDecoder().decode(base64Audio);
    }

    /**
     * 文字转语音 - 支持自定义音色
     * 使用阿里云百炼平台的语音合成服务
     */
    public byte[] textToSpeechWithVoice(String text, String voiceName) throws Exception {
        try {
            // 设置API密钥
            Constants.apiKey = apiKey;

            if (text == null || text.trim().isEmpty()) {
                throw new IllegalArgumentException("文本内容不能为空");
            }

            // 文本长度限制
            if (text.length() > 500) {
                text = text.substring(0, 500);
                logger.warn("文本长度超过限制，已截取前500个字符");
            }

            logger.info("开始文字转语音，音色: {}, 文本长度: {}", voiceName, text.length());

            // 根据音色名称选择对应的音色参数
            AudioParameters.Voice voice = getVoiceByName(voiceName);

            // 创建多模态对话实例
            MultiModalConversation conv = new MultiModalConversation();

            // 构建语音合成请求参数
            MultiModalConversationParam param = MultiModalConversationParam.builder()
                    .model(TTS_MODEL)                           // 使用语音合成模型
                    .apiKey(apiKey)
                    .text(text)                                 // 待合成的文本
                    .voice(voice)                              // 使用指定音色
                    .build();

            // 调用语音合成服务
            logger.info("调用阿里云语音合成服务，使用音色: {}", voice);
            MultiModalConversationResult result = conv.call(param);

            if (result != null && result.getOutput() != null && result.getOutput().getAudio() != null) {
                String audioUrl = result.getOutput().getAudio().getUrl();
                logger.info("语音合成成功，音频URL: {}", audioUrl);

                // 下载音频文件并返回字节数组
                byte[] audioBytes = downloadAudioFromUrl(audioUrl);
                logger.info("音频下载完成，大小: {} bytes", audioBytes.length);

                return audioBytes;

            } else {
                logger.warn("语音合成返回空结果");
                throw new Exception("语音合成失败：服务返回空结果");
            }

        } catch (NoApiKeyException e) {
            logger.error("API密钥未配置", e);
            throw new Exception("API密钥未配置，请检查配置文件", e);
        } catch (UploadFileException e) {
            logger.error("语音合成上传失败", e);
            throw new Exception("语音合成上传失败: " + e.getMessage(), e);
        } catch (Exception e) {
            logger.error("文字转语音失败", e);
            throw new Exception("文字转语音失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据音色名称获取对应的音色参数
     */
    private AudioParameters.Voice getVoiceByName(String voiceName) {
        if (voiceName == null || voiceName.trim().isEmpty()) {
            return AudioParameters.Voice.CHERRY; // 默认音色
        }

        switch (voiceName.toLowerCase()) {
            case "chelsie":
                return AudioParameters.Voice.CHELSIE;  // 成熟女声
            case "cherry":
                return AudioParameters.Voice.CHERRY;   // 甜美女声
            case "ethan":
                return AudioParameters.Voice.ETHAN;    // 温柔男声
            case "serena":
                return AudioParameters.Voice.SERENA;   // 知性女声
            default:
                logger.warn("未知音色: {}, 使用默认音色Cherry", voiceName);
                return AudioParameters.Voice.CHERRY;
        }
    }

    /**
     * 获取音频文件的MIME类型
     */
    public String getAudioMimeType(String format) {
        switch (format.toLowerCase()) {
            case "wav":
                return "audio/wav";
            case "mp3":
                return "audio/mpeg";
            case "m4a":
                return "audio/mp4";
            case "ogg":
                return "audio/ogg";
            default:
                return "audio/wav";
        }
    }
}

